package ru.ifmo.filemanager.filesystem;

import static ru.ifmo.filemanager.filesystem.RootDirectory.roots;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

import ru.ifmo.filemanager.core.Core;
import ru.ifmo.filemanager.filesystem.interfaces.Directory;
import ru.ifmo.filemanager.filesystem.interfaces.FileSystemObject;
import ru.ifmo.filemanager.filesystem.interfaces.PluginKeyListener;
import ru.ifmo.filemanager.filesystem.keylistener.FileKeyListener;
import ru.ifmo.filemanager.filesystem.keylistener.KeyRequest;
import ru.ifmo.filemanager.filesystem.requests.*;

;

public class FileSystem {

	private static final String directoryUpString = "..";
	private static List<Directory> currentDirectory = new ArrayList<Directory>();
	private static org.eclipse.swt.widgets.List fileList;
	private static Request currentRequest;
	private static final FileKeyListener keyListener = new FileKeyListener();

	private FileSystem() {
	}

	static final Directory root = new RootDirectory();

	public static boolean registerRoot(String name, FileSystemObject root) {
		if (root == null) {
			throw new NullPointerException();
		}
		synchronized (roots) {
			if (roots.containsKey(name)) {
				return false;
			} else {
				roots.put(name, root);
				return true;
			}
		}
	}

	public static void deregisterRoot(String name) {
		synchronized (roots) {
			if (roots.remove(name) == null) {
				throw new IllegalArgumentException("Root is not registered");
			}
		}
	}

	private static Runnable refreshRoots = new Runnable() {

		public void run() {
			if (currentRequest == null && currentDirectory.size() == 1) {
				currentRequest = new ChangeDirectoryRequest().changeDirectory(
						root, 0);
			}
		}
	};

	public static void refreshRoots() {
		Core.execute(refreshRoots);
	}

	public static Request getCurrentRequest() {
		return currentRequest;
	}

	private static Directory getSelectedDirectory() {
		return currentDirectory.get(currentDirectory.size() - 1);
	}

	public static FileSystemObject getSelectedItem() {
		int index = FileSystem.fileList.getSelectionIndex();

		if (index < 0) {
			return null;
		}

		String itemName = FileSystem.fileList.getItem(index);

		try {
			return getSelectedDirectory().lookup(itemName);
		} catch (IOException e) {
			return null;
		}
	}

	public static void setCurrentRequest(Request currentRequest) {
		FileSystem.currentRequest = currentRequest;
	}

	public static void setUpGUI(org.eclipse.swt.widgets.List fileList) {
		FileSystem.fileList = fileList;

		fileList.addKeyListener(keyListener);

		fileList.addSelectionListener(new SelectionAdapter() {

			public void widgetDefaultSelected(SelectionEvent e) {
				if (currentDirectory.size() == 0 || currentRequest != null) {
					return;
				}
				int index = FileSystem.fileList.getSelectionIndex();

				if (index < 0) {
					return;
				}

				String itemName = FileSystem.fileList.getItem(index);

				if (index == 0 && currentDirectory.size() > 1) {
					DirectoryUp();
					return;
				}

				currentRequest = new ActivateRequest().activate(
						getSelectedDirectory(), itemName);
			}
		});
	}

	private static void DirectoryUp() {
		if (currentDirectory.size() <= 1 || currentRequest != null) {
			return;
		}
		currentRequest = new ChangeDirectoryRequest().changeDirectory(
				currentDirectory.get(currentDirectory.size() - 2), -1);

	}

	public static void init() {

		ru.ifmo.filemanager.local.Plugin.load();
	}

	public static void prepare() {
		currentRequest = new ChangeDirectoryRequest().changeDirectory(root, 1);
	}

	public static void setDirectory(Directory directory, int level,
			String files[]) {
		while (level < 1) {
			currentDirectory.remove(currentDirectory.size() - 1);
			++level;
		}
		currentDirectory.add(directory);

		if (directory instanceof RootDirectory) {
			fileList.setItems(files);
			return;
		}

		String[] outFiles = new String[files.length + 1];

		outFiles[0] = directoryUpString;
		for (int i = 0; i < files.length; i++) {
			outFiles[i + 1] = files[i];
		}

		fileList.setItems(outFiles);
	}

	public static void AddKeyListener(PluginKeyListener listener,
			KeyRequest request) {
		keyListener.AddPluginListener(listener, request);
	}
}